package com.css.gitstats.service.gitlab;

import java.util.List;
import java.util.Objects;

import org.apache.commons.lang3.StringUtils;
import org.gitlab4j.api.GitLabApi;
import org.gitlab4j.api.GitLabApiException;
import org.gitlab4j.api.models.Commit;
import org.gitlab4j.api.models.Group;
import org.gitlab4j.api.models.Project;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.css.gitstats.domain.GitBranch;
import com.css.gitstats.domain.GitGroup;
import com.css.gitstats.domain.GitProject;
import com.css.gitstats.domain.GitProjectStatistics;
import com.css.gitstats.domain.vo.GitProjectQueryCriteria;
import com.css.gitstats.service.GitstatsProjectStatistics;
import com.google.common.collect.Lists;

import lombok.extern.slf4j.Slf4j;

/**
 * 项目统计信息
 */
@Slf4j
@Service
public class GitlabGitstatsProjectStatisticsService implements GitstatsProjectStatistics {
	
	@Autowired
	private GitLabApi gitLabApi;

	/**
	 * 获取项目提交活动
	 * @param gitProjectQueryCriteria
	 * @return
	 * @throws GitLabApiException
	 */
	@Override
	public List<GitProjectStatistics> getProjectActivity(GitProjectQueryCriteria gitProjectQueryCriteria) throws GitLabApiException {
		List<GitProjectStatistics> gitProjectStatisticses = Lists.newArrayList();
		try {
			if(Objects.nonNull(gitProjectQueryCriteria.getGroupId())) {
				gitLabApi.getGroupApi().getGroup(gitProjectQueryCriteria.getGroupId()).getProjects().forEach(p->{
					GitProjectStatistics gitProjectStatistics = new GitProjectStatistics();
					try {
						List<Commit> commits = gitLabApi.getCommitsApi().getCommits(p.getId(), gitProjectQueryCriteria.getBranch(), gitProjectQueryCriteria.getStartTime(), gitProjectQueryCriteria.getEndTime());
						gitProjectStatistics.setCommitNumber(commits.size());
						gitProjectStatistics.setId(p.getId().toString());
						gitProjectStatisticses.add(gitProjectStatistics);
					} catch (GitLabApiException e) {
						log.error(e.getMessage(), e);
					}
				});
			}else if(Objects.nonNull(gitProjectQueryCriteria.getId()) || StringUtils.isNotEmpty(gitProjectQueryCriteria.getPath())) {
				GitProjectStatistics gitProjectStatistics = new GitProjectStatistics();
				Object projectIdOrPath = StringUtils.isNotEmpty(gitProjectQueryCriteria.getPath())?gitProjectQueryCriteria.getPath():gitProjectQueryCriteria.getId();
				List<Commit> commits = gitLabApi.getCommitsApi().getCommits(projectIdOrPath, gitProjectQueryCriteria.getBranch(), gitProjectQueryCriteria.getStartTime(), gitProjectQueryCriteria.getEndTime());
				gitProjectStatistics.setCommitNumber(commits.size());
				gitProjectStatistics.setId(projectIdOrPath.toString());
				gitProjectStatisticses.add(gitProjectStatistics);
			}
		}catch (Exception e) {
			log.error(e.getMessage(), e);
		}
		return gitProjectStatisticses;
	}
	
	
	
	/**
	 * 查询所有项目
	 * @return
	 * @throws GitLabApiException
	 */
	@Override
	public List<GitProject> findProject() throws GitLabApiException {
		List<GitProject> gitProjects = Lists.newArrayList();
		try {
			List<Project> projects = gitLabApi.getProjectApi().getProjects();
			projects.stream().forEach(p->{
				gitProjects.add(mapGitlab2GitProject(p));
			});
		}catch (Exception e) {
			log.error(e.getMessage(), e);
		}
		return gitProjects;
	}
	
	/**
	 * 根据组ID或路径获取项目信息
	 * @param groupIdOrPath
	 * @return
	 * @throws GitLabApiException
	 */
	@Override
	public List<GitProject> getProjectsByGroupIdOrPath(Object groupIdOrPath) throws GitLabApiException {
		List<GitProject> gitProjects = Lists.newArrayList();
		try {
			gitLabApi.getGroupApi().getGroup(groupIdOrPath).getProjects().forEach(p->{
				gitProjects.add(mapGitlab2GitProject(p));
			});
		}catch (Exception e) {
			log.error(e.getMessage(), e);
		}
		return gitProjects;
	}
	
	/**
	 * 根据项目id或路径获取项目信息
	 * @param projectIdOrPath
	 * @return
	 * @throws GitLabApiException
	 */
	@Override
	public GitProject getProjectsByIdOrPath(Object projectIdOrPath) throws GitLabApiException {
		GitProject gitProject = null;
		try {
			Project project = gitLabApi.getProjectApi().getProject(projectIdOrPath);
			if(Objects.nonNull(project)) {
				gitProject = mapGitlab2GitProject(project);
			}
		}catch (Exception e) {
			log.error(e.getMessage(), e);
		}
		return gitProject;
	}
	
	/**
	 * gitlab中的group映射到自定义的project中
	 * @param p
	 * @return
	 */
	private GitProject mapGitlab2GitProject(Project p) {
		GitProject project = new GitProject();
		project.setName(p.getName());
		project.setDescription(p.getDescription());
		project.setId(p.getId());
		project.setWebUrl(p.getWebUrl());
		project.setPath(p.getPath());
		try {
			List<GitBranch> gitBranchs = Lists.newArrayList();
			gitLabApi.getRepositoryApi().getBranches(project.getId()).stream().forEach(b->{
				GitBranch gitBranch = new GitBranch();
				gitBranch.setName(b.getName());
				gitBranch.setCommit(b.getCommit());
				
				gitBranchs.add(gitBranch);
			});
			project.setGitBranchs(gitBranchs);
		} catch (GitLabApiException e) {
			log.error(e.getMessage(), e);
		}
		return project;
	}
	
	/**
	 * 获取组列表
	 * @return
	 */
	@Override
	public List<GitGroup> findGroups() {
		List<GitGroup> groups = Lists.newArrayList();
		try {
			gitLabApi.getGroupApi().getGroups().stream().forEach(p->{
				groups.add(mapGitlab2GitGroup(p));
			});
		} catch (GitLabApiException e) {
			log.error(e.getMessage(), e);
		}
		return groups;
	}
	
	/**
	 * 根据groupId或path查询group
	 * @param groupIdOrPath
	 * @return
	 */
	@Override
	public GitGroup getGroupByIdOrPath(Object groupIdOrPath) {
		GitGroup gitGroup = null;
		try {
			Group group = gitLabApi.getGroupApi().getGroup(groupIdOrPath);
			if(Objects.nonNull(group)) {
				gitGroup = mapGitlab2GitGroup(group);
			}
		} catch (GitLabApiException e) {
			log.error(e.getMessage(), e);
		}
		return gitGroup;
	}
	
	/**
	 * gitlab中的group映射到自定义的group中
	 * @param p
	 * @return
	 */
	private GitGroup mapGitlab2GitGroup(Group p) {
		GitGroup group = new GitGroup();
		group.setName(p.getName());
		group.setFullName(p.getFullName());
		group.setDescription(p.getDescription());
		group.setId(p.getId());
		group.setWebUrl(p.getWebUrl());
		group.setPath(p.getPath());
		return group;
	}
}
